﻿using System;
using System.Collections.Concurrent;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using MuYue.Common;

namespace MuYue
{
    /// <summary>
    /// XML格式保存的K-V型配置文件管理器
    /// </summary>
    public class XmlConfigManager
    {
        #region  配置信息实现

        //1.如果存在配置就采用配置信息
        //2.如果配置文件不存在那么就采用约定的默认值
        //3.存储的方式采用k-v模式
        //4.配置文件具有两种功能 -> 读 写

        // 将cofig->读取出来->

        #endregion

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="fileName">配置文件名</param>
        /// <param name="autoSave">是否保存软件修改的变化</param>
        public XmlConfigManager(string fileName, bool autoSave = true) {

            Utility.CreateDirectoryByFileName(fileName);

            _fileName = fileName;
            _autoSave = autoSave;
            _confDictionary = new ConcurrentDictionary<string, ConcurrentDictionary<string, string>>();
            if (!File.Exists(fileName)) {
                return;
            }

            var xDoc = XDocument.Load(fileName);
            if (xDoc.Root != null) {
                
                var xNodes = xDoc.Root.Elements();

                foreach (var xNode in xNodes) {
                    var _dic = new ConcurrentDictionary<string, string>();
                    foreach (var xElement in xNode.Elements()) {
                        var key = xElement.Attribute("key").Value;
                        var val = xElement.Attribute("value").Value;
                        _dic.TryAdd(key, val);
                    }
                    if (_dic.Keys.Count > 0)
                        _confDictionary.TryAdd(xNode.Name.LocalName, _dic);
                }
            }
        }

        /// <summary>
        /// 配置键值存储
        /// </summary>
        private readonly ConcurrentDictionary<string, ConcurrentDictionary<string, string>> _confDictionary;

        /// <summary>
        /// 配置文件名
        /// </summary>
        private readonly string _fileName;

        /// <summary>
        /// 自动保存变化的标记
        /// </summary>
        private readonly bool _autoSave;


        /// <summary>
        /// 尝试从配置文件中去查询数据
        /// 如果没有查询到就返回默认值
        /// </summary>
        /// <param name="key">配置键</param>
        /// <param name="def">默认值</param>
        /// <param name="domain">从属域分块</param>
        /// <returns></returns>
        public string TryGetValue(string domain, string key, string def = null) {
            ConcurrentDictionary<string, string> _dic;
            if (_confDictionary.TryGetValue(domain, out _dic)) {
                string value;
                if (_dic.TryGetValue(key, out value))
                    return value;
                if (_dic.Keys.Contains(key))
                    return def;
            }

            if (!_confDictionary.Keys.Contains(domain)) {
                _dic = new ConcurrentDictionary<string, string>();
            }

            if (_dic != null && _dic.TryAdd(key, def) && _autoSave) {
                _confDictionary.TryAdd(domain, _dic);
                Save();
            }

            return def;
        }

        /// <summary>
        /// 检查配置变化 如果变化则保存变化
        /// </summary>
        public void Save() {
            //lambada
            using (var writer = XmlWriter.Create(_fileName)) {
                writer.WriteStartDocument();
                writer.WriteStartElement("root");
                lock (_confDictionary) {
                    foreach (var kv in _confDictionary) {
                        writer.WriteStartElement(kv.Key);
                        foreach (var kv2 in kv.Value) {
                            writer.WriteStartElement("add");
                            writer.WriteAttributeString("key", kv2.Key);
                            writer.WriteAttributeString("value", kv2.Value);
                            writer.WriteEndElement();
                        }
                        writer.WriteEndElement();
                    }
                }
                writer.WriteEndElement();
            }
        }
    }
}
